#ifndef TRACE_H
#define TRACE_H

#include <assert.h>

#ifdef NDEBUG

#define trace(...)
#define assertion(...)
#define assert(...)

#else /* !NDEBUG */

void trace0(const char* file, int line, const char* func, const char *fmt, ...);
bool assert0(const char *condition, const char* file, int line, const char* func, const char *fmt, ...);

#ifdef ANDROID

#define assertion(e, ...) (!(e) ? assert0(#e, __FILE__, __LINE__, __func__, ##__VA_ARGS__) : true)
#undef assert
#define assert(e) assertion(e, "")
#define trace(...) trace0(__FILE__, __LINE__, __func__, ##__VA_ARGS__)

#else /* !ANDROID */

#define assertion(e, ...) assert(e)
#ifdef __func__
#define trace(...) trace0(__FILE__, __LINE__, __func__, ##__VA_ARGS__)
#elif defined(__FUNCTION__)
#define trace(...) trace0(__FILE__, __LINE__, __FUNCTION__, ##__VA_ARGS__)
#else
#define trace(...) trace0(__FILE__, __LINE__, "", ##__VA_ARGS__)
#endif

#endif /* ANDROID */

#endif /* NDEBUG */

#endif /* DROID_H */
